﻿/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using EXtremecode.Utils;
using System.Data.Common;
using System.Collections;

namespace EXtremecode.DataAccessLayer.Services
{
    public class DBService : IDBService 
    {
        public DataSet ExecuteFillQuery(ServiceCommand cmd, string accessorName, bool transactionBased)
        {
            DataAccessor dataAccessor = DataAccessorCollection.Instance[accessorName];
            IDbCommand cmdNative = null;
            IDbDataAdapter adapter = null;
            DataSet ds = null;
            try
            {

                cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                adapter = dataAccessor.CreateDataAdapter();
                ds = new DataSet();
                DataAccessorUtil.MakeCloneOfCommand(cmd, cmdNative);
                adapter.SelectCommand = cmdNative;
                adapter.Fill(ds);
                return ds;

            }
            catch(Exception ex)
            {
                if (transactionBased)
                {
                    dataAccessor.Rollback();
                }
                if (ds != null)
                {
                    ds.Dispose();
                }
                throw ex;
            }
            finally
            {
                if (cmdNative != null)
                {
                    cmdNative.Dispose();
                }

                if (adapter is DbDataAdapter)
                {
                    ((DbDataAdapter)adapter).Dispose();
                }
            }
            
            
        }

        public int ExecuteNonQuery(ServiceCommand cmd, string accessorName, bool transactionBased)
        {
            DataAccessor dataAccessor = DataAccessorCollection.Instance[accessorName];
            IDbCommand cmdNative = null;
            try
            {

                cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(cmd, cmdNative);

                try
                {
                    if (!transactionBased)
                    {
                        cmdNative.Connection.Open();
                    }
                    return cmdNative.ExecuteNonQuery();

                }
                finally
                {
                    if (!transactionBased)
                    {
                        cmdNative.Connection.Close();
                    }

                }


            }
            catch (Exception ex)
            {
                if (transactionBased)
                {
                    dataAccessor.Rollback();
                }
                throw ex; 
            }
            finally
            {
                if (cmdNative != null)
                {
                    cmdNative.Dispose();
                }
            }


        }


        public ServiceDataReader ExecuteReader(ServiceCommand cmd, string accessorName, bool transactionBased)
        {
            DataAccessor dataAccessor = DataAccessorCollection.Instance[accessorName];
            IDbCommand cmdNative = null;
            try
            {

                cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(cmd, cmdNative);

                try
                {
                    if (!transactionBased)
                    {
                        cmdNative.Connection.Open();
                    }
                    IDataReader reader = cmdNative.ExecuteReader();


                    List<object[]> data = new List<object[]>();
                    ServiceDataReader serviceReader = new ServiceDataReader(data);
                    
                    try
                    {
                        
                        //collect field names
                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            serviceReader.AddFieldIndex(reader.GetName(i), i);
                        }

                        //retrieve data
                        while (reader.Read())
                        {
                            object[] row = new object[reader.FieldCount];
                            reader.GetValues(row);
                            data.Add(row);
                        }
                    }
                    finally 
                    {
                        reader.Close();
                    }
                    
                   
                    return serviceReader;

                }
                finally
                {
                    if (!transactionBased)
                    {
                        cmdNative.Connection.Close();
                    }

                }


            }
            catch (Exception ex)
            {
                if (transactionBased)
                {
                    dataAccessor.Rollback();
                }
                throw ex;
            }
            finally
            {
                if (cmdNative != null)
                {
                    cmdNative.Dispose();
                }
            }


        }

        public DataSet Update(ServiceDataAdapter adapter,DataSet ds,string accessorName, bool transactionBased)
        {
            DataAccessor dataAccessor = DataAccessorCollection.Instance[accessorName];
            IDbDataAdapter nativeAdapter = null;
            try
            {
                IDbCommand cmdNative = null;
                nativeAdapter = dataAccessor.CreateDataAdapter();

                //Select Command [not required for update operation]
                /*IDbCommand  cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(adapter.SelectCommand, cmdNative);
                nativeAdapter.SelectCommand = cmdNative;*/


                //Insert Command
                cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(adapter.InsertCommand, cmdNative);
                nativeAdapter.InsertCommand = cmdNative;


                //Delete Command
                cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(adapter.DeleteCommand, cmdNative);
                nativeAdapter.DeleteCommand = cmdNative;



                //Update Command
                cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(adapter.UpdateCommand, cmdNative);
                nativeAdapter.UpdateCommand = cmdNative;


                nativeAdapter.Update(ds);
                return ds;

            }
            catch (Exception ex)
            {
                if (transactionBased)
                {
                    dataAccessor.Rollback();
                }
                if (ds != null)
                {
                    ds.Dispose();
                }
                throw ex;
            }
            finally
            {
                if (nativeAdapter != null)
                {
                    if (nativeAdapter.SelectCommand != null)
                    {
                        nativeAdapter.SelectCommand.Dispose();
                    }
                    if (nativeAdapter.UpdateCommand!= null)
                    {
                        nativeAdapter.UpdateCommand.Dispose();
                    }
                    if (nativeAdapter.DeleteCommand != null)
                    {
                        nativeAdapter.DeleteCommand.Dispose();
                    }
                    if (nativeAdapter.InsertCommand != null)
                    {
                        nativeAdapter.InsertCommand.Dispose();
                    }


                    if (nativeAdapter is DbDataAdapter)
                    {
                        ((DbDataAdapter)nativeAdapter).Dispose();
                    }
                }

                
            }
        }



        public DataSet Fill(ServiceDataAdapter adapter, DataSet ds, string accessorName, bool transactionBased)
        {
            DataAccessor dataAccessor = DataAccessorCollection.Instance[accessorName];
            IDbDataAdapter nativeAdapter = null;
            try
            {
                nativeAdapter = dataAccessor.CreateDataAdapter();

                //Select Command 
                IDbCommand  cmdNative = dataAccessor.GetPopulatedCommand(transactionBased);
                DataAccessorUtil.MakeCloneOfCommand(adapter.SelectCommand, cmdNative);
                nativeAdapter.SelectCommand = cmdNative;

                
                 nativeAdapter.Fill(ds);
                 return ds;
                

            }
            catch (Exception ex)
            {
                if (transactionBased)
                {
                    dataAccessor.Rollback();
                }
                if (ds != null)
                {
                    ds.Dispose();
                }
                throw ex;
            }
            finally
            {
                if (nativeAdapter != null)
                {
                    if (nativeAdapter.SelectCommand != null)
                    {
                        nativeAdapter.SelectCommand.Dispose();
                    }

                    if (nativeAdapter is DbDataAdapter)
                    {
                        ((DbDataAdapter)nativeAdapter).Dispose();
                    }
                }


            }
        }



        
    }
}
